package cn.suimg.neo4j.redis;


import cn.suimg.neo4j.util.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;


/**
 * Cache Operator
 */
@Slf4j
@Service
public class CacheOperator {

    /**
     * Redis Connect Pool
     */
    @Resource
    private JedisPool jedisPool;

    /**
     * 重新设置缓存过期时间
     * @param cacheKey
     * @param second
     */
    public void expire(CacheKeys cacheKey, int second) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.expire(cacheKey.getKey(), second);
        log.debug("reset [{}] in db [{}] expires time,second:{}",cacheKey.getKey(),cacheKey.getDb(),second);
        jedis.close();
    }

    /**
     * 判断缓存是否存在
     * @param cacheKey
     * @return
     */
    public Boolean exist(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Boolean exists = jedis.exists(cacheKey.getKey());
        jedis.close();
        return exists;
    }

    public void delete(CacheKeys cacheKey) {
        del(cacheKey);
    }

    public void deleteString(CacheKeys cacheKey) {
        del(cacheKey);
    }

    public void setString(CacheKeys cacheKey, String value, int second) {
        try {
            Jedis jedis = jedisPool.getResource();
            jedis.select(cacheKey.getDb());
            jedis.set(cacheKey.getKey(), value);
            jedis.expire(cacheKey.getKey(), second);
            jedis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getString(CacheKeys cacheKey) {
        return get(cacheKey);
    }

    public void setObject(CacheKeys cacheKey, Object object, int second) {
        set(cacheKey, object, second);
    }

    public void deleteObject(CacheKeys cacheKey) {
        del(cacheKey);
    }

    public <T> T getObject(CacheKeys cacheKey, Class<T> t) {
        return get(cacheKey, t);
    }

    /**
     * 入队
     */
    public Long in(CacheKeys cacheKey, String value) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Long result = jedis.rpush(cacheKey.getKey(), value);
        jedis.close();
        return result;
    }

    /**
     * 出队
     */
    public String out(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        String result = jedis.lpop(cacheKey.getKey());
        jedis.close();
        return result;
    }

    /**
     * 栈/队列长
     */
    public Long length(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Long size = jedis.llen(cacheKey.getKey());
        jedis.close();
        return size;
    }

    /**
     * 置值
     */
    public void set(CacheKeys cacheKey, long index, String value) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.lset(cacheKey.getKey(), index, value);
        jedis.close();
    }

    /**
     * 裁剪
     */
    public void trim(CacheKeys cacheKey, long start, int end) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.ltrim(cacheKey.getKey(), start, end);
        jedis.close();
    }

    /**
     * value 可以为正也可以为负数 正表示增加，负数表示减少
     */
    public Long increment(CacheKeys cacheKey, long value) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        long newValue = jedis.incrBy(cacheKey.getKey(), value);
        jedis.close();
        return newValue;
    }

    public void setShort(CacheKeys cacheKey, Short value) {
        try {
            set(cacheKey, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *
     */
    public Short getShort(CacheKeys cacheKey) {
        String result = get(cacheKey);
        return result == null ? null : Short.valueOf(result);
    }

    /**
     * -------------------------------------------------- Redis Hash ---------------------------------------------------
     */
    public void hset(CacheKeys cacheKey, String field, Object o) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.hset(cacheKey.getKey(), field, JSONUtil.toString(o));
        jedis.close();
    }

    public void hset(CacheKeys cacheKey, String field, Object o, int seconds) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.hset(cacheKey.getKey(), field, JSONUtil.toString(o));
        jedis.expire(cacheKey.getKey(), seconds);
        jedis.close();
    }

    public String hget(CacheKeys cacheKey, String field) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        String text = jedis.hget(cacheKey.getKey(), field);
        jedis.close();
        return text;
    }

    public Map<String, String> hgetAll(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Map<String, String> map = jedis.hgetAll(cacheKey.getKey());
        jedis.close();
        return map;
    }

    public <T> T hget(CacheKeys cacheKey, String field, Class<T> clazz) {
        String text = hget(cacheKey, field);
        if (text == null) {
            return null;
        }
        return JSONUtil.toObject(text, clazz);
    }

    public <T> List<T> hgetList(CacheKeys cacheKey, String field, Class<T> clazz) {
        String text = hget(cacheKey, field);
        if (text == null) {
            return null;
        }
        return JSONUtil.toListObject(text, clazz);
    }

    @SuppressWarnings("unused")
    public void hdel(CacheKeys cacheKey, String field) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Object result = jedis.hdel(cacheKey.getKey(), field);
        jedis.close();
    }

    public Long hincrBy(CacheKeys cacheKey, String field, long value) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        long newValue = jedis.hincrBy(cacheKey.getKey(), field, value);
        jedis.close();
        return newValue;
    }

    /**
     * 往缓存中添加set元素
     *
     * @param cacheKey
     * @param var
     */
    public void sadd(CacheKeys cacheKey, String var) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.sadd(cacheKey.getKey(), var);
        jedis.close();
    }

    /**
     * 删除缓存中指定的元素
     *
     * @param cacheKey
     * @return
     */
    public void srem(CacheKeys cacheKey, String var) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.srem(cacheKey.getKey(), var);
        jedis.close();
    }

    /**
     * 随机从Set当中获取一个值
     *
     * @return
     */
    public String srandom(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        String result = jedis.srandmember(cacheKey.getKey());
        jedis.close();
        return result;
    }

    /**
     * 随机从Set当中获取一堆数据
     *
     * @param cacheKey
     * @param count    如果count>0 则就会拿到这个数量不会重复的数据 反之如果count<0 就会拿到重复数据的数据列表
     * @return
     */
    public List<String> srandom(CacheKeys cacheKey, Integer count) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        List<String> result = jedis.srandmember(cacheKey.getKey(), count);
        jedis.close();
        return result;
    }

    /**
     * 检查Set当中是否存在指定的数据
     *
     * @param cacheKey
     * @param var
     * @return
     */
    public boolean sexist(CacheKeys cacheKey, String var) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Boolean result = jedis.sismember(cacheKey.getKey(), var);
        jedis.close();
        return result;
    }

    /**
     * 查询Set集合当中的长度
     *
     * @param cacheKey
     * @return
     */
    public long slength(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        Long length = jedis.scard(cacheKey.getKey());
        jedis.close();
        return length;
    }

    public List<String> lRange(CacheKeys cacheKey, long start, long end) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        List<String> list = jedis.lrange(cacheKey.getKey(), start, end);
        jedis.close();
        return list;
    }

    /**
     * 随机取出set集合中的一个数据，并删除该集合中的这个数据
     */
    public String spop(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        String result = jedis.spop(cacheKey.getKey());
        jedis.close();
        return result;
    }

    /**
     * ------------------------------------------------- Redis Key Value ------------------------------------------------
     */
    public void set(CacheKeys cacheKey, Object o) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        //如果是String类型的Object直接存储 不需要序列化
        if (o instanceof String) {
            jedis.set(cacheKey.getKey(), (String) o);
        } else {
            jedis.set(cacheKey.getKey(), JSONUtil.toString(o));
        }
        jedis.close();
    }

    public void ladd(CacheKeys cacheKeys, String... o) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKeys.getDb());
        jedis.lpush(cacheKeys.getKey(), o);
        jedis.close();
    }

    public void lclean(CacheKeys cacheKeys) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKeys.getDb());
        jedis.ltrim(cacheKeys.getKey(), 1, -1);
        jedis.close();
    }

    public void set(String key, String value) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(0);
        jedis.set(key, value);
        jedis.close();
    }

    public void set(CacheKeys cacheKey, Object o, int seconds) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());

        //如果是String类型的Object直接存储 不需要序列化
        if (o instanceof String) {
            jedis.set(cacheKey.getKey(), (String) o);
        } else {
            jedis.set(cacheKey.getKey(), JSONUtil.toString(o));
        }
        jedis.expire(cacheKey.getKey(), seconds);
        jedis.close();
    }

    public String get(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        String text = jedis.get(cacheKey.getKey());
        jedis.close();
        return text;
    }

    public <T> T get(CacheKeys cacheKey, Class<T> clazz) {
        String text = get(cacheKey);
        if (text == null) {
            return null;
        }
        return JSONUtil.toObject(text, clazz);
    }

    public <T> List<T> getList(CacheKeys cacheKey, Class<T> clazz) {
        String text = get(cacheKey);
        if (text == null) {
            return null;
        }
        return JSONUtil.toListObject(text, clazz);
    }

    public void del(CacheKeys cacheKey) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(cacheKey.getDb());
        jedis.del(cacheKey.getKey());
        jedis.close();
    }

    public void flushRedis(int db) {
        Jedis jedis = jedisPool.getResource();
        jedis.select(db);
        jedis.flushAll();
    }
}
